package com.gopay.cashier.web.controller.cloud;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.gopay.common.constants.microdone.EnumMicroScene;
import com.gopay.common.util.RequestUtils;
import ocx.AESWithJCE;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.gopay.cashier.common.exception.WebException;
import com.gopay.cashier.domain.bean.LoginUser;
import com.gopay.cashier.web.command.BankPayChannelCommand;
import com.gopay.cashier.web.command.BankPayWay;
import com.gopay.cashier.web.command.ExpressPoundageVo;
import com.gopay.cashier.web.command.GopayChannelCommand;
import com.gopay.cashier.web.utils.BisBankBusinessProdConvertUtil;
import com.gopay.cashier.web.utils.CashierConfig;
import com.gopay.cashier.web.utils.DigestUtil;
import com.gopay.common.constants.cust.CustCorpInfoConstants;
import com.gopay.common.constants.cust.CustPersonInfoConstants;
import com.gopay.common.constants.cust.UserInfoConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.trans.GatewaySource;
import com.gopay.common.constants.trans.OrderFeePayer;
import com.gopay.common.constants.trans.PayChannel;
import com.gopay.common.constants.trans.TxnStaCode;
import com.gopay.common.constants.trans.UserType;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.domain.UserInfo;
import com.gopay.common.domain.acps.AcctStatus;
import com.gopay.common.domain.acps.FrezCode;
import com.gopay.common.domain.acps.PayPasswordStatus;
import com.gopay.common.domain.acps.model.AcctMastBean;
import com.gopay.common.domain.cashier.PayDoneResult;
import com.gopay.common.domain.cashier.PayWay;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cust.CustCorpInfo;
import com.gopay.common.domain.cust.CustPersonInfo;
import com.gopay.common.domain.poundage.PoundageRes;
import com.gopay.common.domain.user.UserPayPwdResult;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.PwdControlUtil;
import com.gopay.common.util.ReflectionUtil;
import com.gopay.remote.order.MainOrderField;

/**
 * Created by HJY on 2015/5/5.
 * 网关支付 银行卡支付
 * 支付确认 差额支付 国付宝账户支付
 */
@Controller
@RequestMapping("/sec/cloud")
public class CloudPayConfirm00100Controller extends CloudBaseController {
    protected static final String PORTAL_URL = CashierConfig.get(CashierConfig.PORTAL_URL);
    protected static final String CLOUD_URL = CashierConfig.get(CashierConfig.CLOUD_URL);
    private static final String CAS_URL = CashierConfig.get(CashierConfig.CAS_SERVER_URL);
   

    @RequestMapping(value = "/00100/pay/confirm.shtml")
    public ModelAndView execute(BankPayChannelCommand bankCommand,GopayChannelCommand gopayCommand) throws GopayException {
        printRequest("CloudPayConfirm00100Controller--云账户confirm,command="+bankCommand);
        //add by fanghw 20160524
        if(StringUtils.isNotBlank(bankCommand.getPayBankCodeAll())){
            String selBankCode=bankCommand.getPayBankCodeAll().split("-")[1];
            if(PayChannel._01.value.equals(bankCommand.getPayChannel())){
                bankCommand.setPersonalPayBankCode(selBankCode);
            }else if(PayChannel._51.value.equals(bankCommand.getPayChannel())){
                bankCommand.setCorpPayBankCode(selBankCode);
            }
        }
        
        /**保证支付的用户和登录的用户为同一个用户  20160629  zhg.zhang  start**/
        ModelAndView mv=checkPayUser(getRequest().getParameter(GOPAY_ORDER_ID));
        if(mv!=null){
        	return mv;
        }
        /**保证支付的用户和登录的用户为同一个用户  20160629  zhg.zhang  end**/
        if(bankCommand.getPayWay() == BankPayWay.F){
            //登录后网银支付
            return submit(bankCommand,gopayCommand);
        }else{
            //余额、差额支付
            return balPay(bankCommand,gopayCommand);
        }
    }

	private ModelAndView checkPayUser(String orderId) throws WebException {
		//String orderId = getRequest().getParameter(GOPAY_ORDER_ID);
        CpsGenMainOrder order = getMainOrder(orderId, true);
        if(!StringUtils.equals(getLoginUser().getUser().getCustId(), order.getPayCustId())){
        	/*HttpServletRequest request = getRequest();
        	request.setAttribute(FIELD_ERR_MSG, "Bug");*/
        	ModelAndView mav = new ModelAndView();
        	mav.setViewName("redirect:/pay/cloud/order.shtml"+"?orderKey="+ DigestUtil.getSha1Digest(order.getGopayOrderId())+ "&orderId=" + order.getGopayOrderId());
        	return mav;
        }
        return null;
	}

    private ModelAndView balPay(BankPayChannelCommand bankCommand,GopayChannelCommand gopayCommand) throws GopayException {
        printRequest();
        //充值订单
        CpsGenMainOrder order = getMainOrder(getRequest().getParameter(GOPAY_ORDER_ID), true);
        // 验证
        if(!validate(bankCommand,gopayCommand, order)){
            return next(order,bankCommand, gopayCommand);
        }
        return next(order,bankCommand,gopayCommand);
    }

    //网关支付  余额支付提交入口
    @RequestMapping(value = "/00100/pay/submit.shtml")
    public ModelAndView submit(BankPayChannelCommand bankCommand,GopayChannelCommand gopayCommand) throws GopayException {
        printRequest();
        String orderId = getRequest().getParameter(GOPAY_ORDER_ID);
        //新密码控件 add by wangdong start
        String mcryptKey = "";
        String status = ProcCodeConstants.PROC_CODE_000S1000;
        LoginUser oprInfo = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        try {
            if(bankCommand.getPayWay() != BankPayWay.F && !StringUtils.equals(bankCommand.getAntiPhish(),"1")){
                mcryptKey = (String) getRequest().getSession().getAttribute("mcrypt_key");
                getRequest().getSession().removeAttribute("mcrypt_key");
                if(StringUtils.isBlank(mcryptKey)){
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E5120, "浏览器刷新后，请重新输入密码");
                }
                if (StringUtils.isEmpty(gopayCommand.getPayPassword())){
                    gopayCommand.setPayPassword(getRequest().getParameter("password"));
                }
            }
            //新密码控件 add by wangdong end
            /**保证支付的用户和登录的用户为同一个用户  20160629  zhg.zhang  start**/
            ModelAndView mv=checkPayUser(orderId);
            if(mv!=null){
                status = "支付的用户和登录的用户非同一个用户";
                return mv;
            }
            /**保证支付的用户和登录的用户为同一个用户  20160629  zhg.zhang  end**/

            //校验当前登录用户是否通过实名认证  add by fanghw 20151113
            if(bankCommand.getPayWay() != BankPayWay.F){
                checkPayCustRealNameCertify(getLoginUser());
            }

            CpsGenMainOrder order = getMainOrder(orderId, true);
            // 验证
            if(!validateSubmit(bankCommand, gopayCommand, order,mcryptKey)){
                status = bankCommand.getErrMsg();
                return next(order,bankCommand, gopayCommand);
            }
            //防钓鱼校验
            ModelAndView check = checkAntiPhish(bankCommand,"/sec/00100/pay/submit.shtml?orderKey="+getRequest().getParameter("orderKey")+"&orderId="+orderId);
            if(check != null) {
                status = "防钓鱼校验未通过";
                return check;
            }
            //bankCommand.getPayWay() == BankPayWay.F
            //校验   手续费承担方放开之后的一些特殊情况
            check(bankCommand,order);

            updateOrder(bankCommand,order);
            order = getMainOrder(orderId, true);
            if(bankCommand.getPayWay() != BankPayWay.A){//非余额全额支付
                BankPayChannelCommand inchargeCommand = saveInchargeOrder(bankCommand, order);
                CpsGenMainOrder inchargeOrder = getMainOrder(inchargeCommand.getInChargeOrderId(), true);
                updateOrderProcess(inchargeOrder);
                //rimsProcess(inchargeOrder);
                return bankPay(inchargeOrder);
            }else{
                //rimsProcess(order);
                completeOrder(order);
                return new ModelAndView("redirect:/cloud/00100/express/progress.shtml?orderKey="+getRequest().getParameter("orderKey")+"&t=0&orderId="+orderId);
            }
            //新密码控件 add by wangdong start
        } catch (GopayException e) {
            status = e.getErrMsg()==null?e.getErrCode():e.getErrMsg();
            throw e;
        }finally {
            try {
                if(bankCommand.getPayWay() != BankPayWay.F && !StringUtils.equals(bankCommand.getAntiPhish(),"1")){
                    logMicrodone(getRequest(),mcryptKey, EnumMicroScene.CLOUDAT_CASHIER_BALANCE_PAY.getCode(),orderId,status,oprInfo.getUser());
                }
            } catch (Exception e1) {
                logger.error("云账户网关账户支付，密码控件记录入库异常",e1);
            }
        }
        //新密码控件 add by wangdong end
    }

    private void check(BankPayChannelCommand bankCommand, CpsGenMainOrder order) throws WebException {
		if(bankCommand.getPayWay() == BankPayWay.F){
			//如果是网银支付  校验付款方是否收款锁定   目前网关支付是做一笔00500充值，如果收款锁定cps入账  zzg
			AcctMastBean acct=acctTransService.getAccount(order.getPayAcct());
			logger.error(acct.getAccStatus());
			if(!"A".equals(acct.getAccStatusStr())){
				if("F".equals(acct.getAccStatusStr())){
					if("FUL".equals(acct.getFrezCodeStr())){
						logger.error("收付锁定");
						throw new WebException(ProcCodeConstants.PROC_CODE_100E3008);
					}
					if("CRE".equals(acct.getFrezCodeStr())){
						logger.error("收款锁定");
						throw new WebException(ProcCodeConstants.PROC_CODE_100E3008);
					}
					
					
				}
			}
			
			/*if (!AcctStatus.A.equals(acctMastBean.getAccStatus())) {
	            if (AcctStatus.F.equals(acctMastBean.getAccStatus())) {
	                // 如果账户全冻结,借方冻结,则禁止交易
	                if (FrezCode.FUL.equals(acctMastBean.getFrezCode()) || FrezCode.CRE.equals(acctMastBean.getFrezCode())) {
	                    throw new ServiceCPSException(ProcCodeConstants.PROC_CODE_100E3008, "账户冻结");
	                }
	                if(FrezCode.FUL.equals(acctMastBean.getFrezCode())){
	                	throw new ServiceCPSException(ProcCodeConstants.PROC_CODE_100E3008, "收付锁定");
	                }
	                if (FrezCode.CRE.equals(acctMastBean.getFrezCode())){
	                    throw new ServiceCPSException(ProcCodeConstants.PROC_CODE_100E3008, "收款锁定");
	                }
	            } else {
	                throw new ServiceCPSException(ProcCodeConstants.PROC_CODE_100E3002, "账户状态异常");
	            }*/
			
		}
	}

	private String completeOrder(CpsGenMainOrder order) throws GopayException {
        PayDoneResult r = new PayDoneResult();
        r.setSuccess(true);
        r.setPayWay(PayWay.AcctPay);
        r.setOrderId(order.getGopayOrderId());
        String result = cashierPayCallbackService.finish(r);
        return result;
    }

    private BankPayChannelCommand saveInchargeOrder(BankPayChannelCommand command,CpsGenMainOrder order) throws WebException {
        BankPayChannelCommand inchargeCommand = new BankPayChannelCommand();
        ReflectionUtil.copyProperties(inchargeCommand, command);
        String inchargeOrderId = "";
        PayChannel payChannel = PayChannel.get(command.getPayChannel());
        // 计算银行卡实际支付金额，如果是全额支付，则为订单金额；如果是差额支付，则为订单金额减去账户可用余额
        BigDecimal actualPayAmt = getActualPayAmt(command, order);
        LoginUser user = getLoginUser();
        String custId = (null == user || null == user.getUser()) ? "-" : user.getUser().getCustId();
        /**** 20160901 jiaoshuai 网关支付去掉充值订单begin ****/
        /*try {
            logger.error("调用cps创建支付充值订单.BEGIN.call cps for saving incharge order." + command);
            inchargeOrderId = cashierPayCallbackService.saveInchargeOrder(order.getGopayOrderId(),actualPayAmt.toString(), payChannel.value, command.getPayBankCode(), custId);
            logger.error("调用cps创建支付充值订单.END.call cps for saving incharge order." + inchargeOrderId + ", " + command);
        } catch (GopayException e) {
            logger.error("调用cps创建充值订单发生错误！shortfallpay saveInchargeOrder error!" + command, e);
            throw new WebException(e.getErrCode());
        }
        inchargeCommand.setInChargeOrderId(inchargeOrderId);*/
        inchargeCommand.setInChargeOrderId(order.getGopayOrderId());
        /**** 20160901 jiaoshuai 网关支付去掉充值订单end ****/
        return inchargeCommand;
    }

    private  ModelAndView next(CpsGenMainOrder order,BankPayChannelCommand bankCommand,GopayChannelCommand gopayCommand) throws WebException {
        ModelAndView mav = new ModelAndView("/cloud/00100/content/acct/payConfirm");
        BankPayWay payWay = bankCommand.getPayWay();
        mav.addObject("payWay",payWay.toString());

        DecimalFormat df = new DecimalFormat("0.00");
        BigDecimal payAmt = order.getMerTxnAmt();
        if(payWay == BankPayWay.S){//差额支付
            
        	 throw new WebException(ProcCodeConstants.PROC_CODE_100E6027);
        	
        }else if(payWay == BankPayWay.A){
        	//支付金额需要加佣金  如果付款方承担手续费需要加手续费
        	//order.getOrderFeePayer()
        	BigDecimal total=payAmt;
        	if(BigDecimal.ZERO.compareTo(order.getMerCommAmt())<0){
        		total=total.add(order.getMerCommAmt());
        	}
        	if(OrderFeePayer.PAY_PAYER.value.equals(order.getOrderFeePayer())){
        		PoundageRes res=getPoundageRes(order,PayChannel._52);
        		//order.setFeeAmt(res.getOrderRealFeeAmt());
        		total=total.add(res.getOrderRealFeeAmt());
        		 mav.addObject("order", getOrderInfo(order.getGopayOrderId(),res.getOrderRealFeeAmt()));
        	}else{
        		mav.addObject("order", getOrderInfo(order.getGopayOrderId()));
        	}
           // mav.addObject("acctPayAmt", df.format(payAmt));
            mav.addObject("acctPayAmt", total);
           
        }
        mav.addObject("payAmt", df.format(payAmt));
      
        mav.addObject("orderId", order.getGopayOrderId());
        mav.addObject("gopayAcctId", gopayCommand.getGopayAcctId());
        mav.addObject("formhash", setReqAttr(KEY_FORM_HASH, getRandom(32)));// 防止hack
        
        mav.addObject("cloudat_url",CLOUD_URL);
        //mav.addObject("portal_url",PORTAL_URL);
        mav.addObject("cas_server_url", CAS_URL);
        
        mav.addObject("temp",bankCommand);
        // 增加校验使用动态口令卡的权限
			String custId = getLoginUser().getUser().getCustId();
			boolean flag = userDcPwdManager.getDCAuth(custId);
			if (flag) {
				mav.addObject("haveDcAuth", "1");// 1表示有吧
			}
			// end
        return mav;
    }

    private  ModelAndView bankPay(CpsGenMainOrder order) throws WebException {
        String orderDate = DateUtils.format(order.getGopayTxnTm());
        /**系统加固   发送BIS交易金额  1.首先获取结算金额  2.结算金额无值，取总金额     zhg.zhang 20160712 start**/
        
        BigDecimal amount=order.getSettleAmt()!=null
        		&&BigDecimal.ZERO.compareTo(order.getSettleAmt())<0
        		?order.getSettleAmt():order.getTotalOrderAmt();
        logger.info("order settleAmt="+order.getSettleAmt()+""
        		+ ",totalOrderAmt="+order.getTotalOrderAmt()+",orderId="+order.getGopayOrderId());
        /**系统加固   发送BIS交易金额  1.首先获取结算金额  2.结算金额无值，取总金额     zhg.zhang 20160712 end**/
        //BigDecimal amount = order.getTotalOrderAmt();根据上面的取，注释掉原代码
        String bank = order.getOutStlmId();
        String payChannel = order.getPayChannel();

        getRequest().getSession().removeAttribute(CAS_GOPAY_USER);
        ModelAndView mav = new ModelAndView("pay/bankPayForBis");
        mav.addObject("orderId", order.getGopayOrderId());
        mav.addObject("amount", amount.toString());
        mav.addObject("orderDate", orderDate);
        mav.addObject("userType", "");
        mav.addObject("bank", bank);
        mav.addObject("bisUrl", CashierConfig.get(CashierConfig.BIS_URL));
        mav.addObject("bankBusProd", BisBankBusinessProdConvertUtil.getBisBankBusinessProd(PayChannel.get(payChannel)).value);
        /****采购部需求，网关支付给银行发送订单的时候抓取该交易的商户订单号，显示在“订单说明”字段里   20160623 jiaoshuai start****/
        String description = "";
        
        CpsGenMainOrder  transferOrder = getInchargeOrgOrder(order, false);
        if(transferOrder !=null) {
            String merOrderId = transferOrder.getMerOrderId();
            /*String recvCustName = "";
            CustCorpInfo custCorpInfo = custCorpInfoService.get(transferOrder.getMainRecvCustId());
            if(custCorpInfo != null) {
                recvCustName = custCorpInfo.getCorpName();
            }*/
            description = merOrderId;
        }
        mav.addObject("paymentAccInfo",description);
        logger.error("orderId=["+order.getGopayOrderId()+"],amount=["+amount.toString()+"],bank=["+bank+"],paymentAccInfo=["+description+"]");
        /****采购部需求，网关支付给银行发送订单的时候抓取该交易的商户订单号，显示在“订单说明”字段里   20160623 jiaoshuai end****/
        
        setB2BBankConfig(mav,PayChannel.get(payChannel),bank);
        return mav;
    }

    private void updateOrder(BankPayChannelCommand command, CpsGenMainOrder order) throws WebException {
        Map<MainOrderField, String> values = new HashMap<MainOrderField, String>();
        LoginUser loginUser = getLoginUser();
        //计算手续费
        ExpressPoundageVo epv = getPoundageRes(order,command);
        PayChannel payChannel = epv.getPayChannel();
        PoundageRes p = epv.getPoundageRes();

        if(loginUser!=null){
            values.put(MainOrderField.PAY_CUST_ID, loginUser.getUser().getCustId());
            values.put(MainOrderField.PAY_ACCT, command.getGopayAcctId());
        }
        values.put(MainOrderField.PAY_CHANNEL, payChannel.toString());
        values.put(MainOrderField.OUT_STLM_ID, command.getPayBankCode());
        values.put(MainOrderField.ORDER_DEAL_AMT, p.getOrderDealAmt().toString());
        values.put(MainOrderField.ORDER_REAL_FEE_AMT, p.getOrderRealFeeAmt().toString());

        /**远程IP地址 songefengli 20160922**/
        values.put(MainOrderField.REMOTE_IP, RequestUtils.getRemoteRealIpAddr(getRequest()));

        //云账户 计算总金额  总金额=交易金额+手续费+佣金
        if(IntTxnCd._00100.value.equals(order.getGopayIntTxnCd())
				&&GatewaySource.GATEWAY_SOURCE_06.value.equals(order.getGatewaySource())
				&&order.getMerCommAmt().compareTo(BigDecimal.ZERO)>0
        		){
        	//values.put(MainOrderField.TOTAL_ORDER_AMT, (p.getTotalAmt().add(order.getMerCommAmt())).toString());
        	/**结算金额： 网银付款更新结算金额字段  系统加固   zhg.zhang 20160712 start**/
            values.put(MainOrderField.SETTLE_AMT, p.getSettleAmt().add(order.getMerCommAmt()).toString());
            /**结算金额： 网银付款更新结算金额字段  系统加固   zhg.zhang 20160712 end**/
            /**** add by jiaoshuai 20160905 云账户网关支付，重复支付，原订单做帐时按照totalOrderAmt作的，有问题，需要将totalOrderAmt的值赋值为settleAmt begin ****/
            values.put(MainOrderField.TOTAL_ORDER_AMT, p.getSettleAmt().add(order.getMerCommAmt()).toString());
            /**** add by jiaoshuai 20160905 云账户网关支付，重复支付，原订单做帐时按照totalOrderAmt作的，有问题，需要将totalOrderAmt的值赋值为settleAmt end ****/
        	
        }else{
        	/**结算金额： 网银付款更新结算金额字段  系统加固   zhg.zhang 20160712 start**/
            values.put(MainOrderField.SETTLE_AMT, p.getSettleAmt().toPlainString());
            /**结算金额： 网银付款更新结算金额字段  系统加固   zhg.zhang 20160712 end**/
            /**** add by jiaoshuai 20160905 云账户网关支付，重复支付，原订单做帐时按照totalOrderAmt作的，有问题，需要将totalOrderAmt的值赋值为settleAmt begin ****/
            //values.put(MainOrderField.TOTAL_ORDER_AMT, p.getTotalAmt().toString());
            values.put(MainOrderField.TOTAL_ORDER_AMT, p.getSettleAmt().toPlainString());
            /**** add by jiaoshuai 20160905 云账户网关支付，重复支付，原订单做帐时按照totalOrderAmt作的，有问题，需要将totalOrderAmt的值赋值为settleAmt end ****/
        }
        values.put(MainOrderField.TOTAL_ORDER_FEE_AMT, p.getTotalFeeAmt().toString());
        values.put(MainOrderField.ORDER_FEE_PAYER, p.getOrderFeePayer().value);
        values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_30101.value + "");
        
        
        
        
        // 如果是收款方承担手续费，且手续费金额大于订单金额，中断交易，防止实际交易金额为负数。
        if (OrderFeePayer.REC_PAYER.equals(p.getOrderFeePayer())) {
            if (1 == p.getTotalFeeAmt().compareTo(order.getMerTxnAmt())) {
                logger.error("手续费金额大于订单金额，中断交易！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>merTxnAmt["
                        + order.getMerTxnAmt() + "]! " + command + ", " + order);
                throw new WebException(ProcCodeConstants.PROC_CODE_100E5055);
            }
        }

        try {
            logger.error("调用cps更新订单状态.BEGIN.call cps update mainOrder." + command + ", " + order + ", " + values);
            mainOrderUpdateService.payUpdate(order.getGopayOrderId(), values);
            logger.error("调用cps更新订单状态.END.call cps update mainOrder." + command + ", " + order);
        } catch (GopayException e) {
            logger.error("调用cps更新订单状态出错！call cps update mainOrder exception!" + command + ", " + order, e);
            throw new WebException(e.getErrCode());
        }
        //下面的校验都是根据不同的手续费承担方  网关支付需要进行的余额校验
        if(command.getPayWay() == BankPayWay.F){
        	   
            //手续费选择收款方付手续费，网关支付选择企业网银付款：此时应该有收款方可用余额大于等于手续费金额
      		if(StringUtils.equals(OrderFeePayer.REC_PAYER.value, order.getOrderFeePayer())){
      			AcctMastBean revAcct=acctTransService.getAccount(order.getMainRecvAcct());
      			if(new BigDecimal(revAcct.getAvaAmt()).compareTo(p.getTotalFeeAmt())<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9107);
      			}
      		}
      		//手续费选择商城付手续费，网关支付选择企业网银付款：此时应该有商城可用余额大于等于手续费金额
      		if(StringUtils.equals(OrderFeePayer.MER_PAYER.value, order.getOrderFeePayer())){
      			AcctMastBean merAcct=acctTransService.getAccount(order.getRemark1());
      			if(new BigDecimal(merAcct.getAvaAmt()).compareTo(p.getTotalFeeAmt())<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9107);
      			}
      		}
        	
        }
        else if(command.getPayWay() == BankPayWay.A){
        	//手续费选择付款方付手续费，网关支付选择企业虚拟账户付款：此时应该有子账户可用余额大于等于（交易金额+手续费金额+佣金金额）的校验
        	if(StringUtils.equals(OrderFeePayer.PAY_PAYER.value, order.getOrderFeePayer())){
      			AcctMastBean payAcct=acctTransService.getAccount(order.getPayAcct());
      			BigDecimal total=p.getTotalAmt();
      			
      			if(BigDecimal.ZERO.compareTo(order.getMerCommAmt())<0){
      				total=total.add(order.getMerCommAmt());
      			}
      			if(BigDecimal.ZERO.compareTo(p.getTotalFeeAmt())<0){
      				total=total.add(p.getTotalFeeAmt());
      			}
      			if(new BigDecimal(payAcct.getAvaAmt()).compareTo(total)<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9108);
      			}
      		}
        	
        	//手续费选择收款方付手续费，网关支付选择企业虚拟账户付款：此时应该有付款方可用余额大于等于（交易金额+佣金）；
        	//收款方可用余额大于等于手续费金额
      		if(StringUtils.equals(OrderFeePayer.REC_PAYER.value, order.getOrderFeePayer())){
      			AcctMastBean payAcct=acctTransService.getAccount(order.getPayAcct());
      			BigDecimal total=p.getOrderDealAmt();
      			
      			if(BigDecimal.ZERO.compareTo(order.getMerCommAmt())<0){
      				total=total.add(order.getMerCommAmt());
      			}
      			if(new BigDecimal(payAcct.getAvaAmt()).compareTo(total)<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9110);
      			}
      			
      			AcctMastBean revAcct=acctTransService.getAccount(order.getMainRecvAcct());
      			if(new BigDecimal(revAcct.getAvaAmt()).compareTo(p.getTotalFeeAmt())<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9107);
      			}
      			
      		}
        	//手续费选择商城付手续费，网关支付选择企业虚拟账户付款：此时应该有付款方可用余额大于等于（交易金额+佣金）；
      		//商城可用余额大于等于手续费金额
      		if(StringUtils.equals(OrderFeePayer.MER_PAYER.value, order.getOrderFeePayer())){
      			AcctMastBean payAcct=acctTransService.getAccount(order.getPayAcct());
      			BigDecimal total=p.getOrderDealAmt();
      			
      			if(BigDecimal.ZERO.compareTo(order.getMerCommAmt())<0){
      				total=total.add(order.getMerCommAmt());
      			}
      			if(new BigDecimal(payAcct.getAvaAmt()).compareTo(total)<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9110);
      			}
      			
      			AcctMastBean merAcct=acctTransService.getAccount(order.getRemark1());
      			if(new BigDecimal(merAcct.getAvaAmt()).compareTo(p.getTotalFeeAmt())<0){
      				throw new WebException(ProcCodeConstants.PROC_CODE_100E9107);
      			}
      			
      		}
        	
        	
        }
        
     
        
        
        
    }

    private void updateOrderProcess(CpsGenMainOrder order) throws WebException {
        Map<MainOrderField, String> values = new HashMap<MainOrderField, String>();
        values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_30101.value + "");
        try {
            mainOrderUpdateService.updateMany(order.getGopayOrderId(), values);
        } catch (GopayException e) {
            throw new WebException(e.getErrCode());
        }
    }

    private boolean validate(BankPayChannelCommand command,GopayChannelCommand gopayCommand, CpsGenMainOrder order) throws GopayException {
        HttpServletRequest request = getRequest();
        LoginUser loginUser = getLoginUser();
        if(loginUser == null){
            throw new WebException(ProcCodeConstants.PROC_CODE_100W1006);
        }
        if(command.getPayWay() != BankPayWay.A){
            if (StringUtils.isBlank(command.getPayBankCode())) {
                logger.error(this.getClass() + "没有选择银行！ no bank selected!!" + command);
                throw new WebException(ProcCodeConstants.PROC_CODE_200E1001);
            }
            if (StringUtils.isBlank(command.getPayChannel())) {
                logger.error(this.getClass() + "没有选择银行类型！ no paychannel selected!!" + command);
                throw new WebException(ProcCodeConstants.PROC_CODE_200E1001);
            }
        }

        if (null == order) {
            logger.error("找不到订单！order not exits!" + command);
            throw new WebException(ProcCodeConstants.PROC_CODE_100E5041);
        }
        if (TxnStaCode.TXN_STA_CD_30000.value != (order.getTxnStaCd())) {
            logger.error("订单状态不对！txn_sta_cd wrong!" + order);
            throw new WebException(ProcCodeConstants.PROC_CODE_100E5042);
        }
        if(StringUtils.equals(loginUser.getUser().getCustId(), order.getMainRecvCustId()) || (StringUtils.isNotBlank(command.getGopayAcctId()) && StringUtils.equals(command.getGopayAcctId(), order.getMainRecvAcct()))){
            throw new WebException(ProcCodeConstants.PROC_CODE_100E5011);
        }
        UserInfo userInfo = loginUser.getUser();
        if (null == userInfo || UserInfoConstants.USER_STAT_CANCEL.equals(userInfo.getUserStat())) {
            logger.error("用户不存在或尚未登录！user not exist or not login! " + request.getRemoteUser());
            throw new WebException(ProcCodeConstants.PROC_CODE_100E2001);
        }
        if (!UserInfoConstants.USER_STAT_NORMAL.equals(userInfo.getUserStat())) {
            logger.error("用户状态异常：" + userInfo.getCustId());
            throw new WebException(ProcCodeConstants.PROC_CODE_100E2002);
        }
        String userType = userInfo.getUserType();
        if (UserInfoConstants.USER_TYPE_PERSON.equals(userType)) {
            CustPersonInfo info = custPersonInfoQueryManager.get(userInfo.getCustId());
            if (info == null || CustPersonInfoConstants.CUST_STAT_CANCEL.equals(info.getCustStat())) {
                throw new WebException(ProcCodeConstants.PROC_CODE_100E5001);
            }
            if (!CustPersonInfoConstants.CUST_STAT_NORMAL.equals(info.getCustStat())) {
                throw new WebException(ProcCodeConstants.PROC_CODE_100E5002);
            }
        } else if (userType.startsWith("2")) {
            CustCorpInfo info = custCorpInfoService.get(userInfo.getCustId());
            if (info == null || CustCorpInfoConstants.CORP_STAT_CANCEL.toString().equals(info.getCorpStat())) {
                throw new WebException(ProcCodeConstants.PROC_CODE_100E5001);
            }
            if (!CustCorpInfoConstants.CORP_STAT_NORMAL.toString().equals(info.getCorpStat())) {
                throw new WebException(ProcCodeConstants.PROC_CODE_100E5002);
            }
        } else {
            throw new WebException(ProcCodeConstants.PROC_CODE_100E1027);
        }

        //校验收款方
        checkRecvCustStatus(0, order.getMainRecvCustId());
        AcctMastBean acct = acctTransService.getAccount(order.getMainRecvAcct());
        if (null == acct) {
            logger.error("账户不存在,acctId=" + order.getMainRecvAcct());
            throw new WebException(ProcCodeConstants.PROC_CODE_100E6012);
        }
        if (AcctStatus.F.equals(acct.getAccStatus())) {
            if (FrezCode.CRE.equals(acct.getFrezCode()) || FrezCode.FUL.equals(acct.getFrezCode())) {
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E3025, "账户[" + order.getMainRecvAcct()
                        + "]处于冻结状态[" + acct.getFrezCode() + "]，无法入款");
            }
        }
        return true;
    }

    private boolean validateSubmit(BankPayChannelCommand command,GopayChannelCommand gopayCommand, CpsGenMainOrder order,String mcryptKey) throws GopayException {
        boolean resCheck = validate(command,gopayCommand,order);
        if(resCheck && command.getPayWay() != BankPayWay.F && !StringUtils.equals(command.getAntiPhish(),"1")){
            String payPwd = null;
            try {
//                payPwd = PwdControlUtil.decryptPwd(getRequest(), gopayCommand.getPayPassword());
                //新密码控件 add by wangdong start
                payPwd= AESWithJCE.getResult(mcryptKey, gopayCommand.getPayPassword());//调用解密接口.获得密码明文。
                //新密码控件 add by wangdong end
            } catch (Exception e) {
                logger.error("密码解密发生错误！！ Error occurs while decrypting password!!" + command, e);
                command.setErrId("1");
                command.setErrMsg("密码解密发生错误");
                return false;
            }
            UserPayPwdResult res = userPayPwdManager.verifyPayPwd(getLoginUser().getUser().getUserId(), payPwd);
            if(res == null || !res.isVerifySuccess()){
                /**** 云账户网关支付支付密码错误信息提示     jiaoshuai 20160728 start****/
                String errMsg = "支付密码校验失败";
                if(res != null) {
                    errMsg = res.getErrorMsg();
                    int todayErrCount = res.getTodayErrCount();
                    if(todayErrCount != 0) {
                        if(todayErrCount < UserInfoConstants.MAX_PAYPWD_DAY_ERR) {
                            StringBuffer sb = new StringBuffer("支付密码累计错误").append(todayErrCount);
                            sb.append("次（当天错误次数大于等于").append(UserInfoConstants.MAX_PAYPWD_DAY_ERR).append("次时,支付密码将被锁定）");
                            errMsg = sb.toString();
                        } else {
                            errMsg = "支付密码输错次数已达上限，支付密码被锁定。 可通过“找回支付密码”解锁，或联系客服完成支付密码解锁";
                        } 
                    }
                    if(res.getPayPwdStatus() !=null && PayPasswordStatus.LOCK_PERMANENT.equals(res.getPayPwdStatus())) {
                        errMsg = "支付密码输错次数已达上限，支付密码被锁定。 可通过“找回支付密码”解锁，或联系客服完成支付密码解锁";
                    }
                }
                command.setErrMsg(errMsg);
                //command.setErrMsg(res==null ? "支付密码校验失败":res.getErrorMsg());
                /**** 云账户网关支付支付密码错误信息提示     jiaoshuai 20160728 end****/
                command.setErrId("1");
                return false;
            }
            
            //校验动态口令卡
            //String custId=getLoginUser().getUser().getCustId();
            //将原有的根据custId查询动态口令信息修改称为根据userID查询动态口令
            String userId = getLoginUser().getUser().getUserId();
            //boolean flag = userDcPwdManager.getDCAuth(custId);
            boolean flag = userDcPwdManager.getDCAuthbyUserId(userId);
            if (flag) {// 有使用的才校验
    			String dcPass = getRequest().getParameter("dcpass");
    			String dcErrMesg="";
    			try {
    				dcErrMesg = userDcPwdManager.getErrMesgByUserId(userId, dcPass);
    			} catch (Exception e) {
    				command.setDcErrMesg("校验动态口令卡出现异常");
    				 return false;
    			}
    			if (!"".equals(dcErrMesg)) {
    				command.setDcErrMesg(dcErrMesg);
    				 return false;
    			}
    		} 
        }
        return  true;
    }

    private PayChannel getPayChannel(){
        PayChannel payChannel = null;
        LoginUser loginUser = getLoginUser();
        if(loginUser!=null){
            UserType userType = UserType.get(loginUser.getUser().getUserType());
            if (UserType.Person.equals(userType)) {
                payChannel = PayChannel._02;
            } else {
                payChannel = PayChannel._52;
            }
        }
        return payChannel;
    }
    /**
     * 云账户获取支付方式
     * @Description: 跟普通网关支付银行卡支付方式代码同步，解决云账户网关支付去掉充值订单之后，银行卡支付不收手续费报错的bug 
     * @param command
     * @return 
     * @author jiaoshuai
     */
    private PayChannel getPayChannel(BankPayChannelCommand command){
        PayChannel payChannel = null;
        //String payAcct = command.getGopayAcctId();
        LoginUser loginUser = getLoginUser();
        if(loginUser!=null){
            UserType userType = UserType.get(loginUser.getUser().getUserType());
            //余额支付
            if (BankPayWay.A.equals(command.getPayWay())) {
                if (UserType.Person.equals(userType)) {
                    payChannel = PayChannel._02;
                } else {
                    payChannel = PayChannel._52;
                }
            } else if(BankPayWay.F.equals(command.getPayWay())) {
                payChannel = PayChannel.get(command.getPayChannel());
            }
        }
        return payChannel;
    }

    /**
     * 计算正确的差额支付金额，同时进行校验
     */
    private BigDecimal getActualPayAmt(BankPayChannelCommand command, CpsGenMainOrder order) throws WebException {
        if (command.isShortfallPay()) {
            BigDecimal orderAmt = order.getMerTxnAmt();
            AcctMastBean acct = acctTransService.getAccount(command.getGopayAcctId());
            if (null == acct) {
                logger.error("账户不存在！acctMast not exist!" + command + ", " + order);
                throw new WebException(ProcCodeConstants.PROC_CODE_000E3001);
            }
            BigDecimal acctBalance = new BigDecimal(acct.getAvaAmt());
            //账户可用余额 + 差额支付金额 = 订单金额
            if(orderAmt.compareTo(acctBalance)==1){
                BigDecimal shortfallPayAmt = orderAmt.subtract(acctBalance);
                return shortfallPayAmt;
            }
        }
        //如果网关支付
        if(IntTxnCd._00100.value.equals(order.getGopayIntTxnCd())){
        	 BigDecimal orderAmt = order.getMerTxnAmt();
        	 BigDecimal shortfallPayAmt=orderAmt.add(order.getMerCommAmt());
        	//并且手续费承担方是付款方
        	 //实际金额=交易金额+佣金+手续费
        	if(OrderFeePayer.PAY_PAYER.value.equals(order.getOrderFeePayer())){
        		shortfallPayAmt=shortfallPayAmt.add(order.getTotalOrderFeeAmt());
        	}
        	//如果不是付款方承担手续费    实际金额=交易金额+佣金
        	return shortfallPayAmt;
        	
        }
        
        return order.getMerTxnAmt();
    }

    protected ExpressPoundageVo getPoundageRes(CpsGenMainOrder order,BankPayChannelCommand command) throws WebException {
        ExpressPoundageVo vo  = new ExpressPoundageVo();
        LoginUser user = getLoginUser();

        if(user == null){
            if(command.getPayWay() != BankPayWay.A && command.getPayChannel() != null){
                PayChannel payChannel = PayChannel.get(command.getPayChannel());
                vo.setPayChannel(payChannel);
                vo.setPoundageRes(getPoundageRes(order, payChannel));
                return vo;
            }
        }else{
            PayChannel payChannel1 = getPayChannel(command);
            PoundageRes res1 = getPoundageRes(order, payChannel1);
            vo.setPayChannel(payChannel1);
            vo.setPoundageRes(res1);
            if(command.getPayWay() != BankPayWay.A && command.getPayChannel() != null){
                PayChannel payChannel2 =  PayChannel.get(command.getPayChannel());
                PoundageRes res2 = getPoundageRes(order, payChannel2);
                int comp = res1.getTotalFeeAmt().compareTo(res2.getTotalFeeAmt());
                if(comp ==-1 || comp ==0){
                    vo.setPayChannel(payChannel2);
                    vo.setPoundageRes(res2);
                }
            }
            return  vo;
        }
        throw new WebException(ProcCodeConstants.PROC_CODE_100E5051);
    }
}
